/*-------------------------------------------------------------------------
 *
 * mxactdesc.c
 *	  访问/transam/multixact.c 的 rmgr 描述例程
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/backend/access/rmgrdesc/mxactdesc.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "access/multixact.h"

static void fc_out_member(StringInfo fc_buf, MultiXactMember *fc_member)
{
	appendStringInfo(fc_buf, "%u ", fc_member->xid);
	switch (fc_member->status)
	{
		case MultiXactStatusForKeyShare:
			appendStringInfoString(fc_buf, "(keysh) ");
			break;
		case MultiXactStatusForShare:
			appendStringInfoString(fc_buf, "(sh) ");
			break;
		case MultiXactStatusForNoKeyUpdate:
			appendStringInfoString(fc_buf, "(fornokeyupd) ");
			break;
		case MultiXactStatusForUpdate:
			appendStringInfoString(fc_buf, "(forupd) ");
			break;
		case MultiXactStatusNoKeyUpdate:
			appendStringInfoString(fc_buf, "(nokeyupd) ");
			break;
		case MultiXactStatusUpdate:
			appendStringInfoString(fc_buf, "(upd) ");
			break;
		default:
			appendStringInfoString(fc_buf, "(unk) ");
			break;
	}
}

void multixact_desc(StringInfo fc_buf, XLogReaderState *fc_record)
{
	char	   *fc_rec = XLogRecGetData(fc_record);
	uint8		fc_info = XLogRecGetInfo(fc_record) & ~XLR_INFO_MASK;

	if (fc_info == XLOG_MULTIXACT_ZERO_OFF_PAGE ||
		fc_info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
	{
		int			fc_pageno;

		memcpy(&fc_pageno, fc_rec, sizeof(int));
		appendStringInfo(fc_buf, "%d", fc_pageno);
	}
	else if (fc_info == XLOG_MULTIXACT_CREATE_ID)
	{
		xl_multixact_create *fc_xlrec = (xl_multixact_create *) fc_rec;
		int			fc_i;

		appendStringInfo(fc_buf, "%u offset %u nmembers %d: ", fc_xlrec->mid,
						 fc_xlrec->moff, fc_xlrec->nmembers);
		for (fc_i = 0; fc_i < fc_xlrec->nmembers; fc_i++)
			fc_out_member(fc_buf, &fc_xlrec->members[fc_i]);
	}
	else if (fc_info == XLOG_MULTIXACT_TRUNCATE_ID)
	{
		xl_multixact_truncate *fc_xlrec = (xl_multixact_truncate *) fc_rec;

		appendStringInfo(fc_buf, "offsets [%u, %u), members [%u, %u)",
						 fc_xlrec->startTruncOff, fc_xlrec->endTruncOff,
						 fc_xlrec->startTruncMemb, fc_xlrec->endTruncMemb);
	}
}

const char * multixact_identify(uint8 fc_info)
{
	const char *fc_id = NULL;

	switch (fc_info & ~XLR_INFO_MASK)
	{
		case XLOG_MULTIXACT_ZERO_OFF_PAGE:
			fc_id = "ZERO_OFF_PAGE";
			break;
		case XLOG_MULTIXACT_ZERO_MEM_PAGE:
			fc_id = "ZERO_MEM_PAGE";
			break;
		case XLOG_MULTIXACT_CREATE_ID:
			fc_id = "CREATE_ID";
			break;
		case XLOG_MULTIXACT_TRUNCATE_ID:
			fc_id = "TRUNCATE_ID";
			break;
	}

	return fc_id;
}
